package com.zyb.lmbackend.controller;

/**
 * 统计相关接口控制器。
 *
 * 提供：
 * - 按任务版本或时间范围统计各类目数量与占比
 * - 按类目获取典型样例（用于前端悬浮卡片展示）
 * - 获取当前启用的类目字典
 */

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zyb.lmbackend.dto.CategoryDictDto;
import com.zyb.lmbackend.config.AppProperties;
import com.zyb.lmbackend.dto.CategoryStatDto;
import com.zyb.lmbackend.dto.TopExampleDto;
import com.zyb.lmbackend.entity.CategoryDict;
import com.zyb.lmbackend.entity.GoodsBackClassified;
import com.zyb.lmbackend.mapper.ClassifyTaskMapper;
import com.zyb.lmbackend.mapper.GoodsBackClassifiedMapper;
import com.zyb.lmbackend.service.CategoryDictService;
import io.swagger.v3.oas.annotations.Operation;
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/api")
public class StatsController {

    private final GoodsBackClassifiedMapper classifiedMapper;
    private final CategoryDictService categoryDictService;
    private final ClassifyTaskMapper classifyTaskMapper;
    private final ObjectMapper objectMapper;
    private final AppProperties appProperties;

    public StatsController(GoodsBackClassifiedMapper classifiedMapper,
                           CategoryDictService categoryDictService,
                           ClassifyTaskMapper classifyTaskMapper,
                           ObjectMapper objectMapper,
                           AppProperties appProperties) {
        this.classifiedMapper = classifiedMapper;
        this.categoryDictService = categoryDictService;
        this.classifyTaskMapper = classifyTaskMapper;
        this.objectMapper = objectMapper;
        this.appProperties = appProperties;
    }

    @Operation(summary = "统计各类目数量与占比")
    @GetMapping("/stats")
    /**
     * 统计各类目数量与占比。
     *
     * 逻辑：
     * - 有时间筛选时直接从明细表按条件聚合
     * - 无时间筛选时从视图 v_category_stats 读取指定版本（默认最新版本）
     */
    public ResponseEntity<List<CategoryStatDto>> stats(
            @RequestParam(required = false) Integer taskVersion,
            @RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) OffsetDateTime dateFrom,
            @RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) OffsetDateTime dateTo) {
        LocalDateTime from = dateFrom == null ? null : dateFrom.toLocalDateTime();
        LocalDateTime to = dateTo == null ? null : dateTo.toLocalDateTime();
        boolean hasDateFilter = from != null || to != null;

        List<CategoryStatDto> rows;
        if (hasDateFilter) {
            // 按时间范围/版本从明细表统计
            rows = classifiedMapper.selectStatsFromTable(taskVersion, from, to);
        } else {
//            前端没有指定版本就默认查自己指定的版本，这样做是因为如果大模型跑一半停了，此时yml文件设置版本为上一次能完成展示学习机数据的版本
            Integer cfgVersion = appProperties.getDEFAULT_STATS_VERSION();
            int version = taskVersion != null
                    ? taskVersion
                    : (cfgVersion != null && cfgVersion > 0 ? cfgVersion : Math.max(1, classifyTaskMapper.selectMaxVersion()));
            // 从物化视图读取指定版本统计
            rows = classifiedMapper.selectStatsFromView(version);
        }
        int total = rows.stream().map(r -> r.getCount() == null ? 0 : r.getCount()).reduce(0, Integer::sum);
        for (CategoryStatDto r : rows) {
            if (total > 0) {
                r.setRatio(r.getCount() * 1.0 / total);
            } else {
                r.setRatio(0.0);
            }
        }
        rows.sort(Comparator.comparing(CategoryStatDto::getCount).reversed());
        return ResponseEntity.ok(rows);
    }

    @Operation(summary = "Get top examples by category code")
    @GetMapping("/stats/top-examples")
    /**
     * 获取某个类目的典型样例（按置信度降序，默认3条）。
     */
    public ResponseEntity<List<TopExampleDto>> topExamples(
            @RequestParam String code, @RequestParam(required = false, defaultValue = "3") Integer limit) {
        int lim = Math.max(1, Math.min(10, Objects.requireNonNullElse(limit, 3)));
        List<GoodsBackClassified> list = classifiedMapper.selectTopExamples(code, lim);
        List<TopExampleDto> dtos = new ArrayList<>();
        for (GoodsBackClassified g : list) {
//            // 脱敏 SN
//            String masked = maskSn(g.getSn());
//            内部使用，不用脱敏
            dtos.add(new TopExampleDto(g.getSn(), g.getBackDetail()));
        }
        return ResponseEntity.ok(dtos);
    }

    @Operation(summary = " 返回大模型已经归纳出来的种类")
    @GetMapping("/categories")
    /**
     * 获取当前启用(is_active=1)的类目字典，用于前端列表与分类允许集。
     */
    public ResponseEntity<List<CategoryDictDto>> categories() {
        List<CategoryDict> list = categoryDictService.list(new LambdaQueryWrapper<CategoryDict>()
                .eq(CategoryDict::getIsActive, (byte) 1));
        List<CategoryDictDto> dtos = list.stream().map(this::toDto).collect(Collectors.toList());
        return ResponseEntity.ok(dtos);
    }

    private CategoryDictDto toDto(CategoryDict e) {
        CategoryDictDto d = new CategoryDictDto();
        d.setCode(e.getCode());
        d.setName(e.getName());
        d.setDefinition(e.getDefinition());
        d.setIsActive(e.getIsActive() == null ? 1 : e.getIsActive().intValue());
        try {
            List<String> kws = e.getKeywords() == null ? List.of() : objectMapper.readValue(e.getKeywords(), new TypeReference<List<String>>(){});
            d.setKeywords(kws);
        } catch (Exception ex) {
            d.setKeywords(List.of());
        }
        return d;
    }

    private String maskSn(String sn) {
        if (sn == null) return null;
        String s = sn.trim();
        if (s.length() <= 8) return s;
        int mid = s.length() / 2;
        int start = Math.max(0, mid - 2);
        int end = Math.min(s.length(), start + 4);
        return s.substring(0, start) + "****" + s.substring(end);
    }

    @Operation(summary = "List available classify versions (distinct, desc)")
    @GetMapping("/classify/versions")
    public ResponseEntity<List<Integer>> listVersions() {
        List<Integer> versions = classifyTaskMapper.selectAllVersions();
        return ResponseEntity.ok(versions);
    }
}
